<?php

class OrganizationalPropertyFactory
{
  
  private static $instance = null;

  private function __construct ()
  {
  
  }

  /**
   * @return OrganizationalPropertyFactory
   */
  public static function getInstance ()
  {
    if (is_null(self::$instance))
    {
      self::$instance = new self();
    }
    return self::$instance;
  }

  public function create (OrganizationalUnit $unit, OrganizationalProperty $property, OrganizationalPropertyType $type, array $values)
  {
    $type_class = $type->getClass();
    $property_class = $property->getClass();
    
    return $this->createFromClassNames($unit, $property, $type_class, $property_class, $values);
  }

  /**
   * <code>
   * Array (
   * 0 => OrganizationalPropertyType
   * OrganizationalProperty => Array (
   * 0 => OrganizationalProperty
   * OrganizationalEntityPropertyAssignment => Array (
   * 0 => OrganizationalEntityPropertyAssignment )
   * OrganizationalUnitPropertyAssignment => Array (
   * 0 => OrganizationalUnitPropertyAssignment,
   * 1 => ... )
   * )
   * )
   * </code>
   * 
   * @param OrganizationalUnit $unit
   * @param array $array
   */
  public function createFromArray (OrganizationalUnit $unit, array $array)
  {
    if (! isset($array[0]) || ! isset($array[0]['OrganizationalProperty']) || ! isset($array[0]['OrganizationalProperty'][0]))
    {
      throw new InvalidArgumentException(sprintf('Array doesn not meet requirements: %s', print_r($array, true)));
    }
    
    $type_class = $array[0]['class'];
    $property_class = $array[0]['OrganizationalProperty'][0]['class'];
    
    $values = array();
    if (isset($array[0]['OrganizationalProperty'][0]['OrganizationalUnitPropertyAssignment'][0]))
    {
      foreach ($array[0]['OrganizationalProperty'][0]['OrganizationalUnitPropertyAssignment'] as $assignment)
      {
        $values['unit'][$assignment['id']] = $assignment['value'];
      }
    }
    elseif (isset($array[0]['OrganizationalProperty'][0]['OrganizationalEntityPropertyAssignment'][0]))
    {
      foreach ($array[0]['OrganizationalProperty'][0]['OrganizationalEntityPropertyAssignment'] as $assignment)
      {
        $values['entity'][$assignment['id']] = $assignment['value'];
      }
    }
    
    return $this->createFromClassNames($unit, $type_class, $property_class, $values);
  }

  protected function createFromClassNames (OrganizationalUnit $unit, OrganizationalProperty $property, $type_class, $property_class, array $values)
  {
    if (is_null($type_class))
    {
      $type_class = 'DefaultOrganizationalPropertyType';
    }
    $type_obj = new $type_class($unit);
    
    if (is_null($property_class))
    {
      $property_class = 'DefaultOrganizationalProperty';
    }
    
    return new $property_class($unit, $property, $type_obj, $values);
  }

}